home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / dpmigcc5.zip / RSX / SOURCE / FS.C < prev    next >
C/C++ Source or Header  |  1994-12-12  |  13KB  |  573 lines

  1. /*****************************************************************************
  2.  * FILE: fs.c                                     *
  3.  *                                         *
  4.  * DESC:                                     *
  5.  *    - file system functions                          *
  6.  *    - sys_close, sys_dup, sys_sup2, sys_lseek                 *
  7.  *    - msdos file operations                          *
  8.  *                                         *
  9.  * Copyright (C) 1993,1994                             *
  10.  *    Rainer Schnitker, Heeper Str. 283, 33607 Bielefeld             *
  11.  *    email: rainer@mathematik.uni-bielefeld.de                 *
  12.  *                                         *
  13.  *****************************************************************************/
  14.  
  15. #include <string.h>
  16. #include <malloc.h>
  17. #include "DPMI.H"
  18. #include "PROCESS.H"
  19. #include "DOSERRNO.H"
  20. #include "CDOSX32.H"
  21. #include "SIGNALS.H"
  22. #include "RMLIB.H"
  23. #include "PRINTF.H"
  24. #include "FS.H"
  25. #include "COPY32.H"
  26. #include "TERMIO.H"
  27.  
  28. #define NIL_FP (struct file *)0
  29.  
  30. struct file rsx_filetab[RSX_NFILES];
  31.  
  32. /*
  33. ** make entries for standard dos_files
  34. */
  35. void init_rsx_filetab()
  36. {
  37.     rsx_filetab[0].f_mode = FMODE_READ;
  38.     rsx_filetab[0].f_count = 1;
  39.     rsx_filetab[0].f_doshandle = 0;
  40.     rsx_filetab[0].f_op = & msdos_fop;
  41.  
  42.     rsx_filetab[1].f_mode = FMODE_WRITE;
  43.     rsx_filetab[1].f_count = 1;
  44.     rsx_filetab[1].f_doshandle = 1;
  45.     rsx_filetab[1].f_op = & msdos_fop;
  46.  
  47.     rsx_filetab[2].f_mode = FMODE_WRITE;
  48.     rsx_filetab[2].f_count = 1;
  49.     rsx_filetab[2].f_doshandle = 2;
  50.     rsx_filetab[2].f_op = & msdos_fop;
  51.  
  52.     rsx_filetab[3].f_mode = FMODE_WRITE;
  53.     rsx_filetab[3].f_count = 1;
  54.     rsx_filetab[3].f_doshandle = 3;
  55.     rsx_filetab[3].f_op = & msdos_fop;
  56.  
  57.     rsx_filetab[4].f_mode = FMODE_WRITE;
  58.     rsx_filetab[4].f_count = 1;
  59.     rsx_filetab[4].f_doshandle = 4;
  60.     rsx_filetab[4].f_op = & msdos_fop;
  61. }
  62.  
  63. /*
  64. ** search for free file pointer
  65. */
  66. int get_empty_proc_filp(void)
  67. {
  68.     int fd, i;
  69.  
  70.     /* search for entry in proc tab */
  71.     for (fd = 0 ; fd < N_FILES ; fd++)
  72.     if (!npz->filp[fd])
  73.         break;
  74.     if (fd >= N_FILES)
  75.     return -EMX_EMFILE;
  76.  
  77.     /* search for entry in rsx_filetab */
  78.     for (i = 0; i < RSX_NFILES; i++)
  79.     if (! rsx_filetab[i].f_count)
  80.         break;
  81.     if (rsx_filetab[i].f_count)
  82.     return -EMX_EMFILE;
  83.  
  84.     rsx_filetab[i].f_count = 1;
  85.     rsx_filetab[i].f_mode = FMODE_READ | FMODE_WRITE;
  86.     npz->filp[fd] = & rsx_filetab[i];
  87.     return fd;
  88. }
  89.  
  90. /*
  91. ** convert handle to real DOS file handle
  92. */
  93. int get_dos_handle(int handle)
  94. {
  95.     if (handle >= N_FILES || !npz->filp[handle])
  96.     return -1;
  97.     else if (npz->filp[handle]->f_doshandle == -1)
  98.     return -2;
  99.     else
  100.     return npz->filp[handle]->f_doshandle;
  101. }
  102.  
  103. /*
  104. ** close a file handle
  105. */
  106. int sys_close(int fd)
  107. {
  108.     struct file * filp;
  109.  
  110.     if (fd >= N_FILES)
  111.     return -EMX_EBADF;
  112.     if (!(filp = npz->filp[fd]))
  113.     return -EMX_EBADF;
  114.     npz->filp[fd] = NIL_FP;
  115.  
  116.     if (filp->f_count == 0) {
  117.     printf("FS error: file %d count is 0\n", fd);
  118.     return 0;
  119.     }
  120.     if (filp->f_count > 1) {
  121.     filp->f_count--;
  122.     return 0;
  123.     }
  124.     if (filp->f_op && filp->f_op->release)
  125.     filp->f_op->release(filp);
  126.     filp->f_count--;
  127.     return 0;
  128. }
  129.  
  130. /*
  131. ** dup a file handle
  132. */
  133. static int dupfd(unsigned int fd, unsigned int arg)
  134. {
  135.     if (fd >= N_FILES || !npz->filp[fd])
  136.     return -EMX_EBADF;
  137.     if (arg >= N_FILES)
  138.     return -EMX_EINVAL;
  139.     while (arg < N_FILES)
  140.     if (npz->filp[arg])
  141.         arg++;
  142.     else
  143.         break;
  144.     if (arg >= N_FILES)
  145.         return -EMX_EMFILE;
  146.     npz->filp[arg] = npz->filp[fd];
  147.     npz->filp[arg]->f_count++;
  148.     return arg;
  149. }
  150.  
  151. int sys_dup2(unsigned int oldfd, unsigned int newfd)
  152. {
  153.     if (oldfd >= N_FILES || !npz->filp[oldfd])
  154.     return -EMX_EBADF;
  155.     if (newfd == oldfd)
  156.     return newfd;
  157.     if (newfd > N_FILES)
  158.     return -EMX_EBADF;
  159.     if (newfd == N_FILES)
  160.     return -EMX_EBADF;
  161.     sys_close(newfd);
  162.     return dupfd(oldfd, newfd);
  163. }
  164.  
  165. int sys_dup(unsigned int fildes)
  166. {
  167.     return dupfd(fildes,0);
  168. }
  169.  
  170. /*
  171. ** read from file handle
  172. */
  173. ARGUSER sys_read(int fd, ARGUSER buf, ARGUSER bytes)
  174. {
  175.     struct file * file;
  176.  
  177.     if (fd >= N_FILES)
  178.     return -EMX_EBADF;
  179.     if (!(file = npz->filp[fd]))
  180.     return -EMX_EBADF;
  181.     if (! file->f_op || ! file->f_op->read)
  182.     return -EMX_EBADF;
  183.     /* tested in cdosx32 **
  184.     if (verify_illegal(npz, buf, bytes)) {
  185.     send_signal(npz, SIGSEGV);
  186.     return -EMX_EINTR;
  187.     } */
  188.     return file->f_op->read(file, buf, bytes);
  189. }
  190.  
  191. /*
  192. ** write to file handle
  193. */
  194. ARGUSER sys_write(int fd, ARGUSER buf, ARGUSER bytes)
  195. {
  196.     struct file * file;
  197.  
  198.     if (fd >= N_FILES)
  199.     return -EMX_EBADF;
  200.     if (!(file = npz->filp[fd]))
  201.     return -EMX_EBADF;
  202.     if (! file->f_op || ! file->f_op->write)
  203.     return -EMX_EBADF;
  204.     /* tested in cdosx32 **
  205.     if (verify_illegal(npz, buf, bytes)) {
  206.     send_signal(npz, SIGSEGV);
  207.     return -EMX_EINTR;
  208.     }
  209.     */
  210.     return file->f_op->write(file, buf, bytes);
  211. }
  212.  
  213. /*
  214. ** seek file handle
  215. */
  216. long sys_lseek(int fd, long off, int orgin)
  217. {
  218.     struct file * file;
  219.  
  220.     if (fd >= N_FILES)
  221.     return -EMX_EBADF;
  222.     if (!(file = npz->filp[fd]))
  223.     return -EMX_EBADF;
  224.     if (! file->f_op || ! file->f_op->lseek)
  225.     return -EMX_EBADF;
  226.     return file->f_op->lseek(file, off, orgin);
  227. }
  228.  
  229. int sys_select(ARGUSER u_select)
  230. {
  231.     DWORD time_val[2];
  232.     struct _select select;
  233.     struct _fd_set fd_in, fd_out;
  234.     struct file *file;
  235.     int nhandles;
  236.     int i;
  237.  
  238.     /* get select struct */
  239.     cpy32_16(DS, u_select, &select, sizeof(select));
  240.  
  241.     if (select.time != 0) {        /* get time struct */
  242.     cpy32_16(DS, select.time, time_val, sizeof(time_val));
  243.     time_val[0] = time_val[0] * 182 / 10;        /* timer tics */
  244.     } else {
  245.     time_val[0] = 0xffffffff;
  246.     }
  247.  
  248.     if (select.readfds)     /* get read fd struct */
  249.     cpy32_16(DS, select.readfds, &fd_in, sizeof(fd_in));
  250.     else
  251.     return -EMX_EINVAL;
  252.  
  253.     memset( &fd_out, 0, sizeof(fd_out));    /* FD_ZERO */
  254.  
  255.     if (select.nfds > 40)
  256.     select.nfds = 40;
  257.  
  258.     nhandles = 0;
  259.     for (i = 0; i < (int)select.nfds; i++) {
  260.     if (!(FD_ISSET(i, &fd_in)))
  261.         continue;
  262.     file = npz->filp[i];
  263.     if (!(file = npz->filp[i]))
  264.         continue;
  265.     if (! file->f_op || ! file->f_op->select)
  266.         continue;
  267.     if (file->f_op->select(file, time_val[0])) {
  268.         FD_SET(i, &fd_out);
  269.         nhandles ++;
  270.     }
  271.     }
  272.  
  273.     if (select.readfds)     /* put read fd struct */
  274.     cpy16_32(DS, select.readfds, &fd_out, sizeof(fd_out));
  275.  
  276.     if (select.writefds)
  277.     bzero32(DS, select.writefds, sizeof(struct _fd_set));
  278.  
  279.     if (select.excepfds)
  280.     bzero32(DS, select.excepfds, sizeof(struct _fd_set));
  281.  
  282.     return nhandles;
  283. }
  284.  
  285. int sys_ioctl(int fd, ARGUSER request, ARGUSER arg)
  286. {
  287.     struct file * file;
  288.  
  289.     if (fd >= N_FILES)
  290.     return -EMX_EBADF;
  291.     if (!(file = npz->filp[fd]))
  292.     return -EMX_EBADF;
  293.     if (! file->f_op || ! file->f_op->ioctl)
  294.     return -EMX_EBADF;
  295.     return file->f_op->ioctl(file, request, arg);
  296. }
  297.  
  298. int sys_pipe(ARGUSER size, ARGUSER arg)
  299. {
  300. #if 0
  301.     return -EMX_EMSDOS;
  302. #else
  303.     int fin, fout;
  304.     struct pipe_info *pi;
  305.     struct file *file;
  306.  
  307.     fin = get_empty_proc_filp();
  308.     fout = get_empty_proc_filp();
  309.     if (fin < 0 || fout < 0) {
  310.     npz->filp[fin]->f_count = 0;
  311.     npz->filp[fout]->f_count = 0;
  312.     return -EMX_EMFILE;
  313.     }
  314.     pi = (struct pipe_info *) malloc (sizeof(struct pipe_info));
  315.     if (!pi) {
  316.     npz->filp[fin]->f_count = 0;
  317.     npz->filp[fout]->f_count = 0;
  318.     return -EMX_ENOMEM;
  319.     }
  320.     if (AllocMem(size, &(pi->memhandle), &(pi->memaddress))) {
  321.     npz->filp[fin]->f_count = 0;
  322.     npz->filp[fout]->f_count = 0;
  323.     free(pi);
  324.     return -EMX_ENOMEM;
  325.     }
  326.     AllocLDT(1, & pi->sel);
  327.     SetBaseAddress(pi->sel, pi->memaddress);
  328.     SetAccess(pi->sel, APP_DATA_SEL, 0);
  329.     SetLimit(pi->sel, size-1);
  330.  
  331.     pi->pos = 0;
  332.     pi->len = 0;
  333.     pi->size = size;
  334.     pi->rd_openers = 0;
  335.     pi->wr_openers = 0;
  336.     pi->readers = 1;
  337.     pi->writers = 1;
  338.  
  339.     file = npz->filp[fin];
  340.     file->f_mode = FMODE_READ;
  341.     file->f_doshandle = -1;
  342.     file->f_op = & pipe_fop;
  343.     file->f_offset = 0;
  344.     file->f_info = (union file_info *) pi;
  345.  
  346.     file = npz->filp[fout];
  347.     file->f_mode = FMODE_WRITE;
  348.     file->f_doshandle = -1;
  349.     file->f_op = & pipe_fop;
  350.     file->f_offset = 0;
  351.     file->f_info = (union file_info *) pi;
  352.  
  353.     store32 (DS, arg, (long) fin);
  354.     store32 (DS, arg + 4, (long) fout);
  355.  
  356.     return 0;
  357. #endif
  358. }
  359.  
  360. /* ----------------------------------------------------------------- */
  361.  
  362. /*
  363. ** MS-DOS
  364. ** fileoperations
  365. */
  366.  
  367. static long msdos_lseek(struct file *filp, long off, int orgin)
  368. {
  369.     long pos;
  370.     if ((pos = rm_lseek(filp->f_doshandle, off, orgin)) == -1L)
  371.     return -emx_errno;
  372.     else
  373.     return pos;
  374. }
  375.  
  376. static ARGUSER msdos_read(struct file *filp, ARGUSER buf, ARGUSER bytes)
  377. {
  378.     return cdosx_read(filp->f_doshandle, buf, bytes);
  379. }
  380.  
  381. static ARGUSER msdos_write(struct file *filp, ARGUSER buf, ARGUSER bytes)
  382. {
  383.     return cdosx_write(filp->f_doshandle, buf, bytes);
  384. }
  385.  
  386. extern int sysemx_select(int handle, DWORD time);
  387. static int msdos_select(struct file *filp, DWORD time)
  388. {
  389.     return sysemx_select(filp->f_doshandle, time);
  390. }
  391.  
  392. extern int sysemx_ioctl(int handle, ARGUSER request, ARGUSER arg);
  393. static int msdos_ioctl(struct file *filp, ARGUSER request, ARGUSER arg)
  394. {
  395.     return sysemx_ioctl(filp->f_doshandle, request, arg);
  396. }
  397.  
  398. static void msdos_release(struct file *filp)
  399. {
  400.     if (filp->f_doshandle <= 4)
  401.     printf("FS error: closing doshandle %d\n", filp->f_doshandle);
  402.     else
  403.     rm_close(filp->f_doshandle);
  404. }
  405.  
  406. struct file_operations msdos_fop =  {
  407.     msdos_lseek,
  408.     msdos_read,
  409.     msdos_write,
  410.     msdos_select,
  411.     msdos_ioctl,
  412.     NULL,   /* special open */
  413.     msdos_release
  414. };
  415.  
  416. /* ----------------------------------------------------------------- */
  417.  
  418. /*
  419. ** pipe         !! JUST A FIRST TEST !!
  420. ** fileoperations
  421. */
  422.  
  423. #define PIPE_EMPTY(pipe)    ((pipe)->len == 0)
  424. #define PIPE_FULL(pipe)     ((pipe)->len == (pipe)->size)
  425. #define PIPE_FREE(pipe)     ((pipe)->size - (pipe)->len)
  426. #define PIPE_END(pipe)        (((pipe)->pos+(pipe)->len)&((pipe)->size-1))
  427. #define PIPE_MAX_READ(pipe)    ((pipe)->size - (pipe)->pos)
  428. #define PIPE_MAX_WRITE(pipe)    ((pipe)->size - PIPE_END(pipe))
  429.  
  430. static long pipe_lseek(struct file *filp, long off, int orgin)
  431. {
  432.     emx_errno = EMX_ESPIPE;
  433.     return -1;
  434. }
  435.  
  436. static ARGUSER pipe_read(struct file *filp, ARGUSER buf, ARGUSER bytes)
  437. {
  438.     struct pipe_info *pi = (struct pipe_info *) filp->f_info;
  439.     long chars, size, read = 0;
  440.  
  441.     if (filp->f_flags & FCNTL_NDELAY) {
  442.     if (PIPE_EMPTY(pi))
  443.         if (pi->writers)
  444.         return -EMX_EAGAIN;
  445.         else
  446.         return 0;
  447.     }
  448.     while (PIPE_EMPTY(pi)) {
  449.     if (!pi->writers)
  450.         return 0;
  451.     if (!schedule())    /* no other processes */
  452.         return -EMX_EPIPE;
  453.     }
  454.     while (bytes > 0 && (size = pi->len)) {
  455.     chars = PIPE_MAX_READ(pi);
  456.     if (chars > bytes)
  457.         chars = bytes;
  458.     if (chars > size)
  459.         chars = size;
  460.     cpy32_32(pi->sel, pi->pos, DS, buf, chars);
  461.     pi->len -= chars;
  462.     pi->pos += chars;
  463.     pi->pos &= (pi->size-1);
  464.     buf += chars;
  465.     bytes -= chars;
  466.     read += chars;
  467.     }
  468.     if (read)
  469.     return read;
  470.     if (pi->writers)
  471.     return -EMX_EAGAIN;
  472.     return 0;
  473. }
  474.  
  475. static ARGUSER pipe_write(struct file *filp, ARGUSER buf, ARGUSER bytes)
  476. {
  477.     struct pipe_info *pi = (struct pipe_info *) filp->f_info;
  478.     long chars, free, written = 0;
  479.  
  480.     if (!pi->readers) {
  481.     send_signal(npz, SIGPIPE);
  482.     return -EMX_EPIPE;
  483.     }
  484.     if (bytes <= pi->size)
  485.     free = bytes;
  486.     else
  487.     free = 1;
  488.  
  489.     while (bytes > 0) {
  490.     while (PIPE_FREE(pi) < free) {        /* not enough space */
  491.         if (!pi->readers) {
  492.         send_signal(npz, SIGPIPE);
  493.         return written ? written : -EMX_EPIPE;
  494.         }
  495.         if (filp->f_flags & FCNTL_NDELAY)
  496.         return written ? written : -EMX_EAGAIN;
  497.         if (!schedule())
  498.         return -EMX_EPIPE;
  499.     }
  500.     while (bytes > 0 && (free = PIPE_FREE(pi))) {
  501.         chars = PIPE_MAX_WRITE(pi);
  502.         if (chars > bytes)
  503.         chars = bytes;
  504.         if (chars > free)
  505.         chars = free;
  506.         cpy32_32(DS, buf, pi->sel, PIPE_END(pi), chars);
  507.         pi->len += chars;
  508.         written += chars;
  509.         bytes -= chars;
  510.         buf += chars;
  511.     }
  512.     if (!schedule())
  513.         return -EMX_EPIPE;
  514.     }
  515.     return written;
  516. }
  517.  
  518. static int pipe_select(struct file *filp, DWORD time)
  519. {
  520.     struct pipe_info *pi = (struct pipe_info *) filp->f_info;
  521.  
  522.     if (filp->f_mode == FMODE_READ)
  523.     return (pi->len != 0L);
  524.     else if (filp->f_mode == FMODE_WRITE)
  525.     return (pi->len != pi->size);
  526.     else
  527.     return 0;
  528. }
  529.  
  530. static int pipe_ioctl(struct file *filp, ARGUSER request, ARGUSER arg)
  531. {
  532.     long temp;
  533.     struct pipe_info *pi = (struct pipe_info *) filp->f_info;
  534.  
  535.     if (request == FIONREAD)
  536.     temp = pi->len;
  537.     else if (request == FGETHTYPE)
  538.     temp = HT_UPIPE;
  539.     else
  540.     return -EMX_EINVAL;
  541.  
  542.     store32(DS, arg, temp);
  543.     return 0;
  544. }
  545.  
  546. static void pipe_release(struct file *filp)
  547. {
  548.     struct pipe_info *pi = (struct pipe_info *) filp->f_info;
  549.  
  550.     if (filp->f_mode & FMODE_READ)
  551.     pi->readers--;
  552.     else if (filp->f_mode & FMODE_WRITE)
  553.     pi->writers--;
  554.     else
  555.     puts("FS error: pipe with no r/w mode");
  556.  
  557.     if (!pi->readers && !pi->writers) {
  558.     FreeMem(pi->memhandle);
  559.     free(pi);
  560.     filp->f_info = NULL;
  561.     }
  562. }
  563.  
  564. struct file_operations pipe_fop =  {
  565.     pipe_lseek,
  566.     pipe_read,
  567.     pipe_write,
  568.     pipe_select,
  569.     pipe_ioctl,
  570.     NULL,   /* special open */
  571.     pipe_release
  572. };
  573.